package cn.itsource.service.impl;

import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.itsource.constants.CacheConstants;
import cn.itsource.constants.ErrorCode;
import cn.itsource.constants.RConst;
import cn.itsource.pojo.LoginInfo;
import cn.itsource.pojo.domain.Login;
import cn.itsource.mapper.LoginMapper;
import cn.itsource.pojo.dto.RegisterDto;
import cn.itsource.pojo.ro.AppLoginRo;
import cn.itsource.pojo.ro.managerLoginRo;
import cn.itsource.pojo.vo.UserInfoVo;
import cn.itsource.pojo.vo.managerInfoVo;
import cn.itsource.result.JSONResult;
import cn.itsource.service.ILoginService;
import cn.itsource.service.WxChatService;
import cn.itsource.utils.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 登录表 服务实现类
 * </p>
 *
 * @author whale
 * @since 2024-07-06
 */
@Service
@Slf4j
public class LoginServiceImpl extends ServiceImpl<LoginMapper, Login> implements ILoginService {

    @Autowired
    private WxChatService wxChatService;

    @Autowired
    private LoginMapper loginMapper;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public JSONResult appLogin(AppLoginRo login) {
        RegisterDto wxChatOpenid = wxChatService.getWxChatOpenid(login.getCode());
        String openid = wxChatOpenid.getOpenid();
        AssertUtil.isNotNull(openid,"获取opneid失败");
        log.info("当前code:{}获取openid失败",login.getCode());

        Login one = super.getOne(new LambdaQueryWrapper<Login>().eq(Login::getOpenId, openid)
                .eq(Login::getType, login.getType()));
        if (one != null) {
            getpermissionList(one);
            //返回token
            String tokenValue = StpUtil.getTokenValue();
            //封装
            UserInfoVo userInfovo = UserInfoVo.toUserInfovo(one, tokenValue);
            return JSONResult.success(userInfovo);
        }

        return JSONResult.error(ErrorCode.WX_CHAT_LOGIN_ERROR);
    }


    @Override
    public JSONResult managerLogin(managerLoginRo login) {
        String username = login.getUsername();
        Long type = login.getType();
        Login one = super.getOne(new LambdaQueryWrapper<Login>().eq(Login::getUsername, username).eq(Login::getType, type));
        AssertUtil.isNotNull(one,"用户名或密码错误");

        //在确定密码对不对
        boolean matches = bCryptPasswordEncoder.matches(login.getPassword(), one.getPassword());
        AssertUtil.isTrue(matches,"用户名或密码错误");
        AssertUtil.isTrue(one.getEnabled(),"账号被禁用");
        List<String> permissionList = getpermissionList(one);
        String tokenValue = StpUtil.getTokenValue();
        one.setPassword(""); //
        //封装返回
        managerInfoVo managerInfoVo = new managerInfoVo(one,permissionList,tokenValue);

        return JSONResult.success(managerInfoVo);
    }

    @Override
    public JSONResult managerOut(Login login) {
        Long id = login.getId();
        StpUtil.logout();
        //StpUtil.logout(id);
        return JSONResult.success();
    }

    @Override
    @Transactional
    public JSONResult managerpass(LoginInfo login) {
        Long id = login.getId();
        String newPassword = login.getNewPassword();
        String encode = bCryptPasswordEncoder.encode(newPassword);
        loginMapper.update(id,encode);
        return JSONResult.success();
    }


    private List<String> getpermissionList(Login one) {
        //登录成功
        StpUtil.login(one.getId(), SaLoginConfig.setExtra("userinfo", one)
                .setExtra("openid",one.getOpenId()));
        //查询数据库，将权限保存在redis里面
        List<String> permissionList = loginMapper
                .selectPermissionByLoginId(Long.valueOf(one.getId().toString()));
        //存入redis
        String key = CacheConstants.CURRENT_LOGIN_PERMISSION + one.getId().toString();
        redisTemplate.opsForValue().set(key,permissionList, RConst.Num.INT_30, TimeUnit.MINUTES);
        return permissionList;
    }
}